home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / amiga_log.c < prev    next >
C/C++ Source or Header  |  1994-05-02  |  20KB  |  731 lines

  1. RCS_ID_C="$Id: amiga_log.c,v 1.41 1994/05/02 19:59:24 jraja Exp $";
  2. /* 
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: amiga_log.c,v $
  9.  * Revision 1.41  1994/05/02  19:59:24  jraja
  10.  * Removed not-used local variable.
  11.  *
  12.  * Revision 1.40  1994/04/22  13:55:46  jraja
  13.  * Fixed the bug in log file/console name change notify function:
  14.  * NATTRACE's DosBase is no more used before initialization.
  15.  *
  16.  * Revision 1.39  1994/02/17  18:21:54  jraja
  17.  * Changed vcsprintf to csprintf.
  18.  *
  19.  * Revision 1.38  1994/02/16  21:49:02  jraja
  20.  * Changed log date formatting to use vcsprintf() with '32-bit' formatting.
  21.  *
  22.  * Revision 1.37  1994/01/23  22:04:57  jraja
  23.  * Fixed void return on log_task().
  24.  *
  25.  * Revision 1.36  1994/01/19  21:39:17  jraja
  26.  * Added Seek()ing to the end of the old log file if necessary.
  27.  *
  28.  * Revision 1.35  1994/01/05  10:07:36  jraja
  29.  * Made ARexx port visible only after API is visible.
  30.  * Moved IntuitionBase open&close to the panic() function.
  31.  * Added static variables for the memory (addrs&sizes) allocated, so that
  32.  * FreeMem() would not crash if configuration is changed.
  33.  * General code & comments clean-up.
  34.  *
  35.  * Revision 1.34  1993/11/14  19:46:43  jraja
  36.  * Fixed off-by-one errors in month & day names.
  37.  *
  38.  * Revision 1.33  1993/11/06  23:51:22  ppessi
  39.  * Changed log message format. Converted to use csprintf where possible.
  40.  *
  41.  * Revision 1.31  1993/10/07  22:41:34  ppessi
  42.  * Added time to the log message.
  43.  *
  44.  * Revision 1.30  1993/08/06  08:58:37  jraja
  45.  * Set required bsdsocket.library version to 2.
  46.  *
  47.  * Revision 1.29  1993/06/04  11:16:15  jraja
  48.  * Fixes for first public release.
  49.  *
  50.  * Revision 1.28  1993/06/01  08:38:04  puhuri
  51.  * Fixed declaration of logOpen. (missing static)
  52.  *
  53.  * Revision 1.27  1993/05/27  16:43:26  puhuri
  54.  * Made better file opening (now tries everything).
  55.  * Add few commets.
  56.  *
  57.  * Revision 1.26  1993/05/17  01:07:47  ppessi
  58.  * Changed RCS version.
  59.  *
  60.  * Revision 1.25  1993/05/05  16:10:02  puhuri
  61.  * Fixes for final demo.
  62.  *
  63.  * Revision 1.24  93/05/04  12:41:31  12:41:31  puhuri (Markus Peuhkuri)
  64.  * Fixed defination of stuffchar(), perdence errors.
  65.  * 
  66.  * Revision 1.23  93/05/03  18:47:48  18:47:48  puhuri (Markus Peuhkuri)
  67.  * Add check to GetLogMsg to avoid calling GetMsg with NULL pointer
  68.  * (So we can call log before NETTRACE is activated, it just does not 
  69.  * success) It also tries to open socket.library when it gots CTRL-F.
  70.  * 
  71.  * Revision 1.22  93/04/29  22:02:04  22:02:04  puhuri (Markus Peuhkuri)
  72.  * Moved configuration structure log_cnf to amiga_log.h
  73.  * 
  74.  * Revision 1.21  93/04/28  19:24:30  19:24:30  puhuri (Markus Peuhkuri)
  75.  * Fixed variables to give reliable configuration.
  76.  * 
  77.  * Revision 1.20  93/04/26  20:34:28  20:34:28  puhuri (Markus Peuhkuri)
  78.  * Converts control-charactes to spaces, Add ability to modify
  79.  * console and log filenames.
  80.  * 
  81.  * Revision 1.19  93/04/26  18:52:07  18:52:07  puhuri (Markus Peuhkuri)
  82.  * Moved closelog() from subr_prf inside of log_deinit() as it was the
  83.  * only place where it was calld. (Was for historial reasons)
  84.  * Moved closing of Dos earlier in log_close to avoid problems in closing.
  85.  * 
  86.  * Revision 1.18  93/04/23  02:27:44  02:27:44  ppessi (Pekka Pessi)
  87.  * Number and length of logging messages made configreable.
  88.  * 
  89.  * Revision 1.17  93/04/21  19:05:26  19:05:26  puhuri (Markus Peuhkuri)
  90.  * Removed panic()'s if log file couldn't be opened/wroted. Add comments.
  91.  * Now uses new structure of log_msg.
  92.  * 
  93.  * Revision 1.16  93/04/20  18:38:01  18:38:01  puhuri (Markus Peuhkuri)
  94.  * Fixed prototype of log_poll, logmask was number of signal, not mask.
  95.  * pointers to *file were automatic variables, now static.
  96.  * 
  97.  * Revision 1.15  93/04/17  17:56:29  17:56:29  puhuri (Markus Peuhkuri)
  98.  * Fixed few trivial errors from previous version. 
  99.  * (Should compile before ci)
  100.  * 
  101.  * Revision 1.14  93/04/17  17:16:51  17:16:51  puhuri (Markus Peuhkuri)
  102.  * Moved REXX-stuff to NETTRACE-task (from amiga_main)
  103.  * 
  104.  * Revision 1.13  93/04/06  15:15:30  15:15:30  jraja (Jarno Tapio Rajahalme)
  105.  * Changed spl function return value storage to spl_t,
  106.  * changed bcopys and bzeros to aligned and/or const when possible,
  107.  * added inclusion of conf.h to every .c file.
  108.  * 
  109.  * Revision 1.12  93/03/20  07:07:11  07:07:11  ppessi (Pekka Pessi)
  110.  * Fixed memory leak caused by task_remove()
  111.  * 
  112.  * Revision 1.11  93/03/12  23:59:17  23:59:17  ppessi (Pekka Pessi)
  113.  * Prototype fixes.
  114.  * 
  115.  * Revision 1.10  93/03/09  13:29:26  13:29:26  puhuri (Markus Peuhkuri)
  116.  * Now stores information of failed log attempts using new function
  117.  * GetLogMsg. (Increments the number of failed, which is then printed
  118.  * (and zeroed) as logging task gets next message (ts handles it))
  119.  * 
  120.  * Revision 1.9  93/03/05  21:10:51  21:10:51  jraja (Jarno Tapio Rajahalme)
  121.  * Fixed includes (again).
  122.  * 
  123.  * Revision 1.8  93/03/05  12:26:58  12:26:58  jraja (Jarno Tapio Rajahalme)
  124.  * Added CloseLibrary() calls to close logDOSBase on exit.
  125.  * 
  126.  * Revision 1.7  93/03/05  03:25:45  03:25:45  ppessi (Pekka Pessi)
  127.  * Compiles with SASC. Initial test version.
  128.  * 
  129.  * Revision 1.6  93/03/04  10:03:51  10:03:51  jraja (Jarno Tapio Rajahalme)
  130.  * Fixed includes.
  131.  * 
  132.  * Revision 1.5  93/03/01  19:09:39  19:09:39  puhuri (Markus Peuhkuri)
  133.  * Add variable.
  134.  * 
  135.  * Revision 1.4  93/02/26  19:42:46  19:42:46  puhuri (Markus Peuhkuri)
  136.  * Modified to use MsgPort as list of free messages.
  137.  * 
  138.  * Revision 1.3  93/02/25  19:33:55  19:33:55  puhuri (Markus Peuhkuri)
  139.  * Cleanup and consistency with other modules, removed amiga.lib stuff,
  140.  * made compatible with SAS, log task has own DOSBase
  141.  * 
  142.  */
  143.  
  144. #include <conf.h>
  145.  
  146. #include <bsdsocket.library_rev.h>
  147.  
  148. #include <sys/param.h>
  149. #include <sys/systm.h>
  150. #include <sys/time.h>
  151.  
  152. #include <exec/exec.h>
  153. #include <dos/dos.h>
  154. #include <dos/dostags.h>
  155. #include <dos/dosextens.h>
  156.  
  157. #include <kern/amiga_includes.h>
  158. #include <sys/syslog.h>
  159. #include <kern/amiga_log.h>
  160. #include <kern/amiga_rexx.h>
  161. #include <utility/date.h>
  162.  
  163. #if __SASC 
  164. #include <proto/dos.h>
  165. #include <proto/utility.h>
  166. #elif __GNUC__
  167. #define DOSBase logDOSBase
  168. #define UtilityBase logUtilityBase
  169. #include <inline/dos.h>
  170. #undef DOSBase
  171. #else 
  172. #error Compiler not supported!
  173. #endif
  174.  
  175. struct MsgPort *logPort,*logReplyPort;
  176.  
  177. static struct Library *logDOSBase = NULL;
  178. static struct Library *logUtilityBase = NULL;
  179.  
  180. extern struct Task *AmiTCP_Task;
  181. extern struct DosLibrary *DOSBase;
  182.  
  183. extern void REGARGFUN stuffchar();
  184. extern int logname_changed(void *p, LONG new);
  185.  
  186. static struct log_msg *log_poll(void);
  187. static void log_task(void);
  188. static void log_close(struct log_msg *msg);
  189. static BPTR logOpen(STRPTR name);
  190.  
  191. static struct log_msg *log_messages = NULL;
  192. static char *log_buffers = NULL;
  193. static LONG log_messages_mem_size, log_buffers_mem_size;
  194. static int GetLogMsgFail;
  195.  
  196.  
  197. UBYTE consoledefname[] = _PATH_CON;
  198. UBYTE logfiledefname[] = _PATH_LOG;
  199. STRPTR logfilename = logfiledefname;
  200. STRPTR consolename = consoledefname;
  201.  
  202.  
  203. struct log_cnf log_cnf = { LOG_BUFS, LOG_BUF_LEN };
  204.  
  205. /*
  206.  * Initialization function for the logging subsystem
  207.  */
  208.  
  209. BOOL 
  210. log_init(void)
  211. {
  212.   struct Message *msg;
  213.   int i;
  214.   ULONG sig;
  215.  
  216.   if (logReplyPort)
  217.     return(TRUE);        /* We're allready initialized */
  218.   
  219.   /*
  220.    * Allocate buffers for log messages.
  221.    * 
  222.    * Save lengths to static variables, since the configuration variables might
  223.    * change.
  224.    */
  225.   log_messages_mem_size = sizeof(struct log_msg) * log_cnf.log_bufs;
  226.   log_buffers_mem_size = log_cnf.log_bufs * log_cnf.log_buf_len * sizeof(char);
  227.   if (log_messages = AllocMem(log_messages_mem_size, MEMF_CLEAR|MEMF_PUBLIC))
  228.     if (log_buffers = AllocMem(log_buffers_mem_size, MEMF_CLEAR|MEMF_PUBLIC)) {
  229.       logPort = NULL; /* NETTRACE will set this on success */
  230.       GetLogMsgFail = 0;
  231.  
  232.       if (logReplyPort = CreateMsgPort()) {
  233.     /*
  234.      * Start the NETTRACE process
  235.      */
  236.     if (CreateNewProcTags(NP_Entry, (LONG)&log_task,
  237.                   NP_Name, (LONG)LOG_TASK_NAME,
  238.                   NP_Priority, LOG_TASK_PRI,
  239.                   TAG_DONE, NULL)) {
  240.       for (;;) {
  241.         /*
  242.          * Wait for a signal for success or failure
  243.          */
  244.         sig = Wait(1<<logReplyPort->mp_SigBit | SIGBREAKF_CTRL_F);
  245.  
  246.         if (sig & SIGBREAKF_CTRL_F && logPort == (struct MsgPort *)-1) {
  247.           /* Initializion failed */
  248.           logPort = NULL;
  249.           break;
  250.         }
  251.         else if (msg = GetMsg(logReplyPort)) { /* Got message back? */
  252.           ReplyMsg(msg);
  253.           logReplyPort->mp_Flags = PA_IGNORE;
  254.           /* 
  255.            * Initialize messages
  256.            */
  257.           for (i = 0; i < log_cnf.log_bufs; i++) {
  258.         log_messages[i].msg.mn_ReplyPort = logReplyPort;
  259.         log_messages[i].msg.mn_Length = sizeof(struct log_msg);
  260.         log_messages[i].level = 0;
  261.         log_messages[i].string = log_buffers+i*log_cnf.log_buf_len;
  262.         log_messages[i].chars = 0;
  263.         PutMsg(logReplyPort, (struct Message *)&log_messages[i]);
  264.           }
  265.           return(TRUE);    /* We're done */
  266.         }
  267.       }
  268.     }
  269.       }
  270.     }
  271.   /*
  272.    * Something went wrong
  273.    */
  274.   log_deinit();
  275.   return(FALSE);
  276. }
  277.  
  278. /*
  279.  * This function may be called only if no other tasks (applications) are 
  280.  * accessing the logging system (the messages, to be exact).
  281.  */
  282. void 
  283. log_deinit(void)
  284. {
  285.   struct log_msg *msg, *dump;
  286.  
  287.   if (logReplyPort) {        /* We have our port? */
  288.     if (logPort) {        /* Logport exists? (=> NETTRACE is running) */
  289.       /*
  290.        * Turn on signalling on returned messages again
  291.        */
  292.       logReplyPort->mp_Flags = PA_SIGNAL;
  293.  
  294.       /*
  295.        * Get a free message, Wait() for it if necessary
  296.        */
  297.       while((msg = (struct log_msg *)GetMsg(logReplyPort)) == NULL) 
  298.     Wait(1<<logReplyPort->mp_SigBit);
  299.  
  300.       /* 
  301.        * Initalize END_MESSAGE
  302.        */
  303.       msg->msg.mn_ReplyPort = logReplyPort;
  304.       msg->msg.mn_Length = sizeof(struct log_msg);
  305.       msg->level = LOG_CLOSE;
  306.  
  307.       PutMsg(logPort, (struct Message *)msg);
  308.       
  309.       for (;;) {
  310.     dump = (struct log_msg *)GetMsg(logReplyPort);
  311.     if (dump) {
  312.       if (dump->level == LOG_CLOSE)    /* got the Close message back */
  313.         break;        /* It was the last one */
  314.     }          
  315.     else
  316.       Wait(1<<logReplyPort->mp_SigBit);
  317.       }
  318.     }
  319.  
  320.     /*
  321.      * ensure that the port is empty
  322.      */
  323.     while(GetMsg(logReplyPort))
  324.       ;
  325.     DeleteMsgPort(logReplyPort);
  326.     logReplyPort = NULL;
  327.   }
  328.   if (log_buffers) {
  329.     FreeMem(log_buffers, log_buffers_mem_size);
  330.     log_buffers = NULL;
  331.   }
  332.   if (log_messages) {
  333.     FreeMem(log_messages, log_messages_mem_size);
  334.     log_messages = NULL;
  335.   }
  336. }
  337.  
  338. /* A little stub for calling GetMsg w/ error reporting and cheking */
  339. struct log_msg *GetLogMsg(struct MsgPort *port)
  340. {
  341.   struct Message *msg;
  342.  
  343.   if (port && (msg = GetMsg(port)))  /* Get a message */
  344.     /* We should have a port, if not-> fail */
  345.     return (struct log_msg *)msg; 
  346.  
  347.   ++GetLogMsgFail;        /* Increment number of failed messages */
  348.   return NULL;
  349. }
  350.  
  351. /*
  352.  * Functions following these defines may be called from the NETTRACE
  353.  * task ONLY! These defines cause the SAS/C to generate calls to
  354.  * dos.library and utility.library using these bases, respectively.
  355.  */
  356. #define DOSBase logDOSBase
  357. #define UtilityBase logUtilityBase
  358.  
  359. struct Library *SocketBase = NULL;
  360. struct Task *Nettrace_Task = NULL;
  361.  
  362. /* Main loop for NETTRACE */
  363. static void SAVEDS
  364. log_task(void)
  365. {
  366.   struct log_msg *initmsg = NULL;
  367.   ULONG rexxmask = 0, logmask = 0, sigmask = 0;
  368.  
  369.   Nettrace_Task = FindTask(NULL); /* Store task pointer for AmiTCP */
  370.  
  371.   /* We need our own DosBase */
  372.   if ((logDOSBase = OpenLibrary(DOSNAME, 0L)) == NULL)
  373.     goto fail;
  374.  
  375.   if ((logUtilityBase = OpenLibrary("utility.library", 37L)) == NULL)
  376.     goto fail;
  377.  
  378.   /* Allocate message to reply startup */
  379.   if ((initmsg = AllocMem(sizeof(struct log_msg), MEMF_CLEAR|MEMF_PUBLIC))
  380.       == NULL)
  381.     goto fail;
  382.  
  383.   /* Create our port for log messages */
  384.   if ((logPort = CreateMsgPort()) == NULL)
  385.     goto fail;
  386.  
  387.   logmask = 1<<logPort->mp_SigBit;
  388.  
  389.   /*
  390.    * Initialize rexx subsystem
  391.    */
  392.   if (!(rexxmask = rexx_init()))
  393.     goto fail;
  394.  
  395.   /*
  396.    * Syncronize with AmiTCP/IP
  397.    */
  398.   initmsg->msg.mn_ReplyPort = logPort;
  399.   initmsg->msg.mn_Length = sizeof(struct log_msg);
  400.   PutMsg(logReplyPort, (struct Message *)initmsg);
  401.   do {
  402.     Wait(logmask);
  403.   } while(initmsg != (struct log_msg *)GetMsg(logPort));
  404.  
  405.   FreeMem(initmsg, sizeof(struct log_msg));
  406.   initmsg = NULL;
  407.  
  408.   sigmask = logmask | rexxmask | SIGBREAKF_CTRL_F;
  409.   
  410.   /* 
  411.    * Main loop of the NETTRACE
  412.    */
  413.   for (;;) {
  414.     ULONG sig;
  415.     struct log_msg *msg;
  416.  
  417.     sig = Wait(sigmask);    /* Wait for signals */
  418.     do {
  419.                 /* Signal from the AmiTCP/IP: API ready */
  420.       if ((sig & SIGBREAKF_CTRL_F) && (SocketBase == NULL)) {
  421.     sig &= ~SIGBREAKF_CTRL_F;
  422.     /*
  423.      * Open a base to our own library so that ARexx message handling
  424.      * can use socket functions.
  425.      * This name does not work with the "nthLibrary" system
  426.      */
  427.     if (SocketBase = OpenLibrary("bsdsocket.library", VERSION)) {
  428.       /*
  429.        * Make our ARexx port public
  430.        */
  431.       rexx_show();
  432.       sigmask &= ~SIGBREAKF_CTRL_F;
  433.     }
  434.       }
  435.  
  436.       if (sig & logmask) {    /* Process log messages,
  437.                  * handles all ones pending.
  438.                  */
  439.     if (msg = log_poll()) {    /* Got an LOG_CLOSE-message? */
  440.       log_close(msg);
  441.       return;
  442.     }
  443.     sig &= ~logmask;
  444.       }
  445.  
  446.       if (sig & rexxmask)    /* One rexx message at time */
  447.     if (SocketBase) {
  448.       if (!rexx_poll()) 
  449.         sig &= ~rexxmask;
  450.     } else
  451.       sig &= ~rexxmask;
  452.  
  453.       sig |= SetSignal(0L, sigmask) & sigmask; /* Signals left? */
  454.     } while (sig);
  455.   }
  456.  
  457.  fail:                
  458.   /* Initializion Failed */
  459.   if (initmsg)
  460.     FreeMem(initmsg, sizeof(struct log_msg));
  461.  
  462.   log_close(NULL);
  463.  
  464.   logPort = (struct MsgPort *)-1;
  465.   /* Inform AmiTCP that we failed */
  466.   Signal(AmiTCP_Task, SIGBREAKF_CTRL_F); 
  467. }
  468.  
  469. static BPTR confile = NULL;
  470. static BPTR logfile = NULL;
  471. static BOOL fileopenfail = FALSE, conopenfail = FALSE;
  472. static BOOL filewritefail = FALSE, conwritefail = FALSE;
  473.  
  474. static char *months =
  475.   "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
  476.  
  477. static char *wdays = 
  478.   "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
  479.  
  480. static char *levels = 
  481.   "emerg\0"
  482.   "alert\0"
  483.   "crit \0"
  484.   "err  \0"
  485.   "warn \0"
  486.   "note \0"
  487.   "info \0"
  488.   "debug";
  489.  
  490. /* 
  491.  * Process all pending log messages 
  492.  */
  493. static
  494. struct log_msg *log_poll()
  495. {     
  496.   struct log_msg *msg;
  497.   ULONG where;
  498.   LONG i;
  499.   struct ClockData clockdata;
  500.  
  501.   /* 28 for date, 14 for level */
  502. # define LEVELBUF 28+14
  503.  
  504.   UBYTE buffer[LEVELBUF];
  505.   static ULONG TotalFail;
  506.  
  507.   /* Process all messages */
  508.   while (msg = (struct log_msg *)GetMsg(logPort)) { 
  509.     struct CSource cs;
  510.  
  511.     /* All except LOG_EMERG to both log and console */
  512.     where = TOLOG;
  513.     if (msg->level != LOG_EMERG)
  514.       where |= TOCONS;
  515.  
  516.     if (msg->level == LOG_CLOSE) {
  517.       return (msg);
  518.     }
  519.  
  520.     cs.CS_Buffer = buffer;
  521.     cs.CS_Length = LEVELBUF;
  522.     cs.CS_CurChr = 0;
  523.  
  524.     Amiga2Date(msg->time, &clockdata);
  525.  
  526.     csprintf(&cs, 
  527. #ifdef HAVE_TIMEZONES
  528.          "%s %s %02d %02d:%02d:%02d %s %4d [%s]: ", 
  529. #else
  530.          "%s %s %02d %02d:%02d:%02d %4d [%s]: ", 
  531. #endif
  532.          wdays + 4 * clockdata.wday,
  533.          months + 4 * (clockdata.month - 1),
  534.          clockdata.mday,
  535.          clockdata.hour,
  536.          clockdata.min,
  537.          clockdata.sec,
  538. #ifdef HAVE_TIMEZONES
  539.          "UCT",    /* Universal Coordinated Time */
  540. #endif
  541.          clockdata.year,
  542.          levels + 6 * ((msg->level <= LOG_DEBUG) ? msg->level : LOG_DEBUG)
  543.          );
  544.  
  545.     /* Remove last newline */
  546.     if (msg->chars > 0 && msg->string[msg->chars - 1] == '\n') {
  547.       msg->chars--;
  548.     }
  549.  
  550.     /* Replace all control chars with space */
  551.     for (i = 0; i < msg->chars; ++i) {
  552.       if ((msg->string)[i] < ' ')
  553.     (msg->string)[i] = ' ';
  554.     }
  555.  
  556.     if (where & TOCONS) {
  557.       /* If console is not open, open it */
  558.       while (confile == NULL) {
  559.     if ((confile = logOpen(consolename)) == NULL) {
  560.       if (!conopenfail) /* log only once */
  561.         log(LOG_ERR,"Opening console log '%s' failed", consolename);
  562.       if (consolename == consoledefname) {
  563.         conopenfail = TRUE;        
  564.         break;
  565.       }
  566.       /* try again with the default name */
  567.       consolename = consoledefname;
  568.       conopenfail = conwritefail = FALSE;
  569.     }
  570.       }
  571.       if (confile != NULL) {
  572.     int error = 
  573.       FPuts(confile, buffer) == -1 ||
  574.         FWrite(confile, msg->string, msg->chars, 1) != 1 ||
  575.           FPutC(confile, '\n') == -1;
  576.     Flush(confile);
  577.     if (error && !conwritefail) {    /* To avoid loops */
  578.       conwritefail = TRUE;
  579.       log(LOG_ERR, "log: Write failed to console '%s'", consolename);
  580.     }
  581.       }
  582.     }
  583.     if (where & TOLOG) {
  584.       /* If log file is not open, open it */
  585.       while (logfile == NULL) {
  586.     if ((logfile = logOpen(logfilename)) == NULL) {
  587.       if (!fileopenfail) /* log only once */
  588.         log(LOG_ERR,"Opening log file '%s' failed", logfilename);
  589.       if (logfilename == logfiledefname) {
  590.         fileopenfail = TRUE;        
  591.         break;
  592.       }
  593.       /* try again with the default name */
  594.       logfilename = logfiledefname;
  595.       fileopenfail = filewritefail = FALSE;
  596.     }
  597.       }
  598.       if (logfile != NULL) {
  599.     int error = 
  600.       FPuts(logfile, buffer) == -1 ||
  601.         FWrite(logfile, msg->string, msg->chars, 1) != 1 ||
  602.           FPutC(logfile, '\n') == -1;
  603.     Flush(logfile);
  604.     if (error && !filewritefail) {    /* To avoid loops */
  605.       filewritefail = TRUE;
  606.       log(LOG_ERR, "log: Write failed to file '%s'", logfilename);
  607.     }
  608.       }
  609.     }
  610.  
  611.     ReplyMsg((struct Message *)msg);
  612.     if (GetLogMsgFail != TotalFail) {
  613.       int t = GetLogMsgFail;    /* Check if we have lost messages */
  614.  
  615.       log(LOG_WARNING,"%ld log messages lost (total %ld lost)\n",
  616.       t - TotalFail, TotalFail);
  617.       TotalFail = t;
  618.     }
  619.   }
  620.   return(NULL);
  621. }  
  622.  
  623. /* Close logging subsystem */
  624. static
  625. void log_close(struct log_msg *msg)
  626. {
  627.   rexx_deinit();
  628.   if (confile)
  629.     Close(confile);
  630.   if (logfile)
  631.     Close(logfile);
  632.   if (logUtilityBase) {
  633.     CloseLibrary(logUtilityBase);
  634.     logUtilityBase = NULL;
  635.   }
  636.   if (logDOSBase) {        /* DOS not needed below */
  637.     CloseLibrary(logDOSBase);
  638.     logDOSBase = NULL;
  639.   }
  640.   if (SocketBase) {
  641.     CloseLibrary((struct Library *)SocketBase);
  642.     SocketBase = NULL;
  643.   }
  644.   /*
  645.    * Make sure that we get to end before task switch
  646.    * and do not get messages from interrupts
  647.    */
  648.   Disable();
  649.  
  650.   if (logPort) {
  651.     struct Message *m;
  652.  
  653.     while (m = GetMsg(logPort))    /* Check for messages and reply */
  654.       ReplyMsg(m);
  655.  
  656.     DeleteMsgPort(logPort);    /* Delete port */
  657.     logPort = NULL;
  658.   }
  659.  
  660.   if (msg)
  661.     ReplyMsg((struct Message *)msg);
  662.  
  663.   Nettrace_Task = NULL;
  664.  
  665.   /*
  666.    * Interrupts are left disabled, 
  667.    * they will be enabled again when this process dies 
  668.    */
  669. }
  670.  
  671. /*
  672.  * Try first open w/ shared lock, then as an old file and finally as a new file
  673.  */
  674. static
  675. BPTR logOpen(STRPTR name)
  676. {
  677.   BPTR file;
  678.  
  679.   if ((file = Open(name, MODE_READWRITE)) ||
  680.       (file = Open(name, MODE_OLDFILE)))
  681.     Seek(file, 0, OFFSET_END);
  682.   else
  683.     file = Open(name, MODE_NEWFILE);
  684.  
  685.   return file;
  686. }
  687.  
  688. /*
  689.  * This function might be called by either AmiTCP or NETTRACE. If the
  690.  * call is done by the AmiTCP, no DOS calls may be done, since the
  691.  * DosBase used by these functions is the one of the NETTRACE, and is
  692.  * not initialized at that time!
  693.  */
  694. int logname_changed(void *p, LONG new)
  695. {
  696.   if (p == &logfilename) {    /* Is logname requested? */
  697.      /*
  698.       * logfile may be non-NULL only if the NETTRACE is already initialized
  699.       */
  700.     if (logfile != NULL) {
  701.       Close(logfile);
  702.       logfile = NULL;
  703.     }
  704.     fileopenfail = filewritefail = FALSE;
  705.     /*
  706.      * setvalue() (who called this) will set the new value when we return 
  707.      * TRUE.
  708.      */
  709.     return TRUE;
  710.   }
  711.  
  712.   if ( p == &consolename ) { /* Name of the console log */
  713.     
  714.     if (confile) { /* only if NETTRACE is already initialized */
  715.       Close(confile);
  716.       confile = NULL;
  717.     }
  718.     conopenfail = conwritefail = FALSE;
  719.     /*
  720.      * setvalue() (who called this) will set the new value when we return 
  721.      * TRUE.
  722.      */
  723.     return TRUE;
  724.   }
  725.  
  726.   /*
  727.    * Some invalid pointer
  728.    */
  729.   return FALSE;
  730. }
  731.